﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace NGridDrawer.Partitions
{
    /// <LastUpdate author="Blaise Braye" Date="15/06/2008 18:37"/>
    /// <summary>
    /// Provide a enumerating way to draw the partition of a grid
    /// by reading its elements from an <see cref="IPartitionDrawer"/> object
    /// </summary>
    public class PartitionDrawer
    {
        /// <summary>
        /// 	<para>Initializes an instance of the <see cref="PartitionDrawer"/> class.</para>
        /// </summary>
        /// <param name="drawer"><see cref="IPartitionDrawer"/> object used to draw the grid of data
        /// </param>
        public PartitionDrawer(IPartitionDrawer drawer)
        {
            Drawer = drawer;
        }

        private PartitionGrid sessionPartition { get; set; }

        /// <summary>Get/Set Component Property</summary>
        protected IPartitionDrawer Drawer { get; set; }

        /// <summary>Get/Set PartitionCursor Property</summary>
        protected IEnumerator<PartitionElement> ElementCursor { get; set; }

        /// <summary>
        /// Get PartitionCount Property 
        /// which is the product of partitionColumns count 
        /// with partitionLevels count</summary>
        public int PartitionCount
        {
            get { return PartitionColumnCount*PartitionLevelCount; }
        }

        /// <summary>Get/Set PartitionLevelCount Property</summary>
        public int PartitionLevelCount
        {
            get { return sessionPartition.PartitionLevelCount; }
        }

        /// <summary>Get/Set PartitionColumnCount Property</summary>
        public int PartitionColumnCount
        {
            get { return sessionPartition.PartitionColumnCount; }
        }

        /// <summary>Get IsInitialized Property</summary>
        public bool IsInitialized
        {
            get { return ElementCursor != null && ElementCursor.Current != null; }
        }

        /// <summary>Get Current element to draw</summary>
        public PartitionElement Current
        {
            get { return ElementCursor.Current; }
        }

        /// <summary>
        /// Move the partition cursor to its first position
        /// </summary>
        /// <returns>boolean value which specifies if reset had an effect according to the partition cursor position</returns>
        public bool ResetPaint()
        {
            bool ret = true;

            if (ElementCursor == null || ElementCursor.Current == null)
                ret = false;
            else
                ElementCursor.Reset();

            return ret;
        }

        /// <summary>Initialize a printing session</summary>
        /// <param name="graphic">graphics used to draw</param>
        /// <param name="clipHeights">Clip heights of partitionColumns (last one is used for the rest)
        /// </param>
        /// <param name="clipWidths">Clip widths of partitionLevels (last one is used for the rest)
        /// </param>
        /// <returns>
        /// Answer to the question "Are there partition to draw?"
        /// </returns>
        public bool InitializeSession(Graphics graphic, float[] clipHeights, float[] clipWidths)
        {
            sessionPartition = Drawer.BuildPartition(graphic, clipHeights, clipWidths);


            ElementCursor = sessionPartition.ElementEnumerator;
            return ElementCursor.MoveNext();
        }

        /// <summary>Paint the current partition element in <paramref name="graphic"/>
        /// </summary>
        /// <param name="graphic">graphics used to draw</param>
        /// <param name="clipBounds">Clip bounds are of partition parts
        /// </param>
        /// <returns>
        /// Answer to the question "Are there partition to draw?"
        /// </returns>
        public bool Paint(Graphics graphic, RectangleF clipBounds)
        {
            if (!IsInitialized)
                throw new InvalidOperationException("PartitionDrawer Must be set on initialized state first");


            Drawer.Paint(graphic, clipBounds, ElementCursor.Current);

            if (!ElementCursor.MoveNext())
                ElementCursor = null;

            return ElementCursor != null;
        }
    }
}